﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Xml.Serialization;

namespace ClassifierLib
{
    /// <summary>
    /// The Rule class represents a single classifier in the system
    /// (This class is synonymous with Classifier in V1 codebase)
    /// </summary>
    [Serializable]
    public class Rule : ICloneable
    {
        private Action _action;
        private Condition _condition;
        private BindingDictionary _statistics = new BindingDictionary();
        private static Dictionary<string, double> _initialStatistics = new Dictionary<string, double>();
        private int _numerosity = 1;

        public Action Action
        {
            get
            {
                return _action;
            }
            set
            {
                _action = value;
            }
        }
        public Condition Condition
        {
            get
            {
                return _condition;
            }
            set
            {
                _condition = value;
            }
        }
        /// <summary>
        /// This dictionary is used to store statistics on individiual rules in the LCS
        /// (note this approach allows other stats to be added without code changes to Rule)
        /// </summary>
        public BindingDictionary Statistics
        {
            get
            {
                return _statistics;
            }
            set
            {
                _statistics = value;
            }
        }

        public static Dictionary<string, double> InitialStatistics
        {
            get
            {
                return _initialStatistics;
            }
        }

        public Rule()
        {
            // create default objects here
            _action = new Action();
            _condition = new Condition();
            AddDefaultStatistics();
        }

        public Rule(Condition Condition, Action Action)
        {
            _action = Action;
            _condition = Condition;
            if (_statistics.Count == 0)
                AddDefaultStatistics();
            else
            {
            }
        }

        /// <summary>
        /// Copy all statistics from static initial values dictionary
        /// </summary>
        private void AddDefaultStatistics()
        {
            foreach (KeyValuePair<string, double> kvp in _initialStatistics)
            {
                _statistics.Add(kvp.Key, kvp.Value);
            }
        }

        /// <summary>
        /// Numerosity of rule, the number of copies of this rule in the set
        /// </summary>
        public int Numerosity
        {
            get
            {
                return _numerosity;
            }
            set
            {
                _numerosity = value;
            }
        }

        #region ICloneable Members

        /// <summary>
        /// Provides a deep clone of Rule, except DOES NOT COPY NUMEROSITY
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            var rule = new Rule(new Condition(new List<double>(Condition.LowerBounds), new List<double>(Condition.UpperBounds)), new Action(Action.Value));

            // copy statistics applied to this element
            foreach (KeyValuePair<string, double> kvp in Statistics)
            {
                rule.Statistics[kvp.Key] = kvp.Value;
            }

            // DOES NOT COPY NUMEROSITY

            rule.Numerosity = 1;

            return rule;
        }

        #endregion
    }
}
